package own.stu.inter.loadbalance.ping;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import own.stu.inter.loadbalance.server.ServerInstance;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

public class ParallelPingStrategy implements IPingStrategy {

    private static Logger logger = LoggerFactory.getLogger(ParallelPingStrategy.class);

    @Override
    public List<Boolean> pingServers(IPing ping, List<ServerInstance> instances) {

        if (instances == null || instances.size() == 0) {
            return new ArrayList<>();
        }
        logger.debug("LoadBalancer:  pingServers executing [{}] instances ", instances);

        List<Boolean> results = Arrays.stream(new Boolean[instances.size()]).collect(Collectors.toList());
        List<CompletableFuture<Boolean>> futures = new ArrayList<>();

        for (int i = 0; i < instances.size(); i++) {
            int finalI = i;
            futures.add(CompletableFuture.supplyAsync(() -> {
                try {
                    if (ping != null) {
                        return ping.isAlive(instances.get(finalI));
                    }
                } catch (Exception e) {
                    logger.error("Exception while pinging Server: '{}'", instances.get(finalI), e);
                }
                return false;
            }).thenApply(v -> results.set(finalI, v)));
        }

        CompletableFuture<Void> f = CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]));

        try {
            return f.thenApply(r -> results).get(); // TODO test check
        } catch (Exception e) {
            throw new RuntimeException("pingServers" + e);
        }
    }
}